Испод хаубе: како се остварује анимација¶
Постоје два суштински различита начина да се анимација оствари.
У једном је главна петља заснована на фрејмовима (енгл. frame-based loop) и њено тело се извршава одређени фиксиран број пута у секунди (обично од 20 до 50). Између свака два фрејма програм паузира своје извршавање. Фреквенцију промене фрејмова је пожељно пажљиво одабрати. Ако је она она превелика објекти се пребрзо крећу по екрану или се иста сцена исцртава већи број пута. Ако је премала, програм је дуго блокиран и не реагује на догађаје, што корисник може осетити (на пример, може да прође одређено време између тренутка када корисник кликне на дугме за искључивање прозора и тренутка када се прозор заиста искључи).
У другом је главна петља заснована на догађајима (енгл. event-based loop) и њено тело се изврши по једном за сваки догађај који наступи, чим догађај наступи. Уводи се тајмер (eнгл. timer) који генерише догађаје у правилним временским интервалима и на сваки откуцај тајмера приказује се наредни фрејм. У овом поглављу ћемо се бавити само анимацијама у којима је главна петља заснована на фрејмовима, док ћемо анимације засноване на догађајима описати у поглављу које се бави анимацијама и догађајима .
Чекање одређен број милисекунди између свака два фрејма¶
Најједноставнији начин да се анимација оствари је следећи облик петље засноване на фрејмовима.
У склопу главне петље прво вршимо цртање. Након тога обрађујемо све
догађаје који су наступили током цртања и чекања, тј. који су
наступили од претходне обраде догађаја (пре свега проверавамо да ли је
корисник искључио прозор тј. да ли је наступио догађај
pg.QUIT
). Ако јесте, прекидамо петљу (било постављањем променљиве
kraj
на True
, било наредбом break
). Затим чекамо одређено
време (на пример, 50 или 100 милисекунди). Чекање можемо остварити
позивом функције pg.time.wait(???)
, чији је параметар дати број
милисекунди (1000 милисекунди је једна секунда).
Док програм чека, сви догађаји који се у међувремену десе се смештају
у једну листу (такозвани ред догађаја). Листа свих догађаја који су
регистровани у реду од тренутка претходног читања тог реда се може
добити функцијом pg.event.get()
. Током обраде догађаја пролазимо
кроз ту листу анализирајући један по један догађај (подсетимо се,
пролазак кроз елементе листе остварује се наредбом облика for
element in lista: ...
). Дакле, у овом сценарију имамо петљу у
петљи. У унутрашњој петљи for
можемо вршити анализу свих догађаја
и реаговати на њих о чему ће више бити речи у поглављу о догађајима.
Коришћење сата¶
Претходно решење не узима у обзир ни трајање исцртавања ни обраде
догађаја (пауза је увек иста, без обзира на то колико су исцртавање и
обрада догађаја трајали). То се може поправити ако се уместо
pg.time.wait
употреби сат који креирамо помоћу pg.Clock
.
На овај начин смо рекли да желимо да се тело петље (тј. цртање) изврши
тачно 25 пута током једне секунде. Заправо, потпуно прецизно говорећи,
овим смо поставили горње ограничење на учесталост извршавања тела
главне петље - оно сигурно неће бити извршено чешће од броја који је
наведен као аргумент функције tick
. Наиме, у неким изузетним
ситуацијама (на пример, ако поставимо велику учесталост, а цртање је
компликовано и захтева пуно времена), систем неће успети да постигне
наведену учесталост и тело петље ће се извршити ређе од онога што је
наведено.
Коришћење библиотеке PygameBg¶
Уз коришћење ове библиотеке, креирање анимација заснованих на фрејмовима је много једноставније (иако „испод хаубе” користи сат и функционише исто како је приказано у претходном примеру). Програми имају наредни облик.
Као и сви претходни, и ови програми почињу отварањем прозора тј. позивом функције pygamebg.open_window. Анимација се започиње на самом крају програма позивом функције pygamebg.frame_loop којој се прослеђује број фрејмова у секунди и функција која се позива при преласку на сваки наредни фрејм. Њен задатак је да промени стање сцене (положај објеката, боје и слично) и да изврши цртање сцене. Да би програми били јаснији, ова два задатка ћемо често раздвајати тако што ћемо у функцији novi_frejm извршавати ажурирање стања сцене, а у посебној функцији crtaj ћемо вршити цртање (ту ћемо функцију позивати из функције novi_frejm, обично на самом њеном крају, након ажурирања вредности свих променљивих).